package com.atguigu.tingshu.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.atguigu.tingshu.album.AlbumInfoFeignClient;
import com.atguigu.tingshu.common.cache.TingqCache;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;


    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Autowired
    private UserVipServiceMapper userVipServiceMapper;
    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Override
    public void updateInfo(UserInfoVo userInfoVo) {
        UserInfo userInfo = new UserInfo();
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setId(userInfoVo.getId());
        userInfoMapper.updateById(userInfo);

    }

    @TingqCache(prefix = "userInfo:")
    @Override
    public UserInfoVo getUserInfo(Long userId) {

        UserInfo userInfo = userInfoMapper.selectById(userId);
        UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
        return userInfoVo;
    }

    @Override
    public Map<Long, Integer> userIsPaidTrackList(Long userId, Long albumId, List<Long> trackIdList) {
        //1.根据userId 根据用户ID+专辑ID查询专辑购买记录   判断 是否购买过专辑(专辑->包含许多声音)? 如果购买,直接将付费标识 职位 1
        LambdaQueryWrapper<UserPaidAlbum> userPaidAlbumLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userPaidAlbumLambdaQueryWrapper.eq(UserPaidAlbum::getUserId, userId);
        userPaidAlbumLambdaQueryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
        Long count = userPaidAlbumMapper.selectCount(userPaidAlbumLambdaQueryWrapper);

        if (count > 0) {
            //代表购买过 ,-> 专辑下的声音都可以听
            Map<Long, Integer> map = new HashMap<>();
            for (Long trackId : trackIdList) {
                //将结果 : 已购买
                map.put(trackId, 1);
            }
            //忘记返回map 导致 用户买到了前端展示的还是没有购买的logo
            return map;
        }

        //2.根据用户ID+声音列表查询 声音 购买集合记录， 判断哪些声音被购买， 哪些没有被购买
        LambdaQueryWrapper<UserPaidTrack> userPaidTrackLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userPaidTrackLambdaQueryWrapper.eq(UserPaidTrack::getUserId, userId);
        userPaidTrackLambdaQueryWrapper.in(UserPaidTrack::getTrackId, trackIdList);
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(userPaidTrackLambdaQueryWrapper);
        if (CollectionUtil.isEmpty(userPaidTrackList)) {
            //2.1 专辑当前页包含声音列表用户一个都没购买
            Map<Long, Integer> map = new HashMap<>();
            for (Long trackId : trackIdList) {
                //将购买结果：未购买
                map.put(trackId, 0);
            }
            return map;
        }

        //2.2 用户有购买声音 判断哪些是被购买，哪些未被购买
        //2.2.1 得到用户已购买声音ID
        List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        //2.2.2 遍历待检测声音ID列表 判断已购买声音记录中是否包含声音ID
        Map<Long, Integer> map = new HashMap<>();
        for (Long trackId : trackIdList) {
            if (userPaidTrackIdList.contains(trackId)) {
                map.put(trackId, 1);
            } else {
                map.put(trackId, 0);
            }
        }
        return map;
    }

    @Override
    public Boolean isPaidAlbum(Long userId, Long albumId) {
        //查询user_paid_album表
        LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPaidAlbum::getUserId, userId);
        queryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
        Long count = userPaidAlbumMapper.selectCount(queryWrapper);
        return count > 0;
    }

    @Override
    public List<Long> getUserPaidTrackList(Long userId, Long albumId) {
        LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPaidTrack::getUserId, userId);
        wrapper.eq(UserPaidTrack::getAlbumId, albumId);
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
        if (CollectionUtil.isNotEmpty(userPaidTrackList)) {
            List<Long> userPaidTrackIdList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            return userPaidTrackIdList;
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveUserPayRecord(UserPaidRecordVo userPaidRecordVo) {
        //1.处理声音购买记录
        if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
            //1.1 根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userPaidTrackMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //1.2 构建声音购买记录新增
            //1.3 远程调用专辑服务获取声音信息
            TrackInfo trackInfo = albumInfoFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0)).getData();
            userPaidRecordVo.getItemIdList().forEach(trackId -> {
                UserPaidTrack userPaidTrack = new UserPaidTrack();
                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
                userPaidTrack.setTrackId(trackId);
                userPaidTrackMapper.insert(userPaidTrack);
            });
        } else if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
            //2.处理专辑购买记录
            //2.1 根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userPaidAlbumMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //2.2 新增专辑购买记录
            userPaidRecordVo.getItemIdList().forEach(albumId -> {
                UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
                userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
                userPaidAlbum.setAlbumId(albumId);
                userPaidAlbumMapper.insert(userPaidAlbum);
            });
        } else if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(userPaidRecordVo.getItemType())) {
            //3.处理会员购买记录
            //3.1-根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserVipService> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserVipService::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userVipServiceMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //3.2-修改用户表VIP状态及失效时间
            Date startTime = new Date();
            //2.1.1 获取用户
            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
            //2.1.2 根据套餐ID查询VIP套餐信息
            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(userPaidRecordVo.getItemIdList().get(0));
            Date expireTime = new Date();


            //刚购买VIP VIP开始时间-当前，过期时间：当前时间+购买月数
            //已是VIP且在有效期，过期时间：现有失效时间+购买月数
            if (userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(new Date())) {
                expireTime = DateUtil.offsetMonth(userInfo.getVipExpireTime(), vipServiceConfig.getServiceMonth());
            } else {
                //首次购买会员-过期时间
                expireTime = DateUtil.offsetMonth(startTime, vipServiceConfig.getServiceMonth());
            }
            userInfo.setIsVip(1);
            userInfo.setVipExpireTime(expireTime);
            userInfoMapper.updateById(userInfo);

            //3.3-新增用户VIP购买记录
            for (Long vipConfigId : userPaidRecordVo.getItemIdList()) {
                UserVipService userVipService = new UserVipService();
                userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
                userVipService.setUserId(userPaidRecordVo.getUserId());
                userVipService.setStartTime(startTime);
                userVipService.setExpireTime(expireTime);
                userVipService.setIsAutoRenew(0);
                userVipService.setNextRenewTime(null);
                userVipServiceMapper.insert(userVipService);
            }

        }
    }

    @Override
    public void updateVipExpireStatus() {
        //1.已经过期会员
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getIsVip, "1");
        queryWrapper.lt(UserInfo::getVipExpireTime, DateUtil.beginOfDay(new Date()));
        List<UserInfo> list = this.list(queryWrapper);
        //2.批量更新
        if (CollectionUtil.isNotEmpty(list)) {
            List<UserInfo> collect = list.stream().map(userInfo -> {
                UserInfo userInfo1 = new UserInfo();
                userInfo1.setIsVip(0);
                userInfo1.setId(userInfo.getId());
                return userInfo1;
            }).collect(Collectors.toList());
            this.updateBatchById(collect);
        }
    }
}
